﻿using System.Linq.Expressions;
using Simple.Repository.Models.Article;
using Simple.Repository.Models.ClassRoom;
using Simple.Repository.Models.Slideshow;
using Simple.Services.System.FileInfo;

namespace Simple.Services.System.ClassRoom
{
    public class SlideshowService : BusinessBaseService
    {
        private readonly SimpleDbContext _context;
        private readonly CacheService _cacheService;
        private readonly FileInfoService _fileInfoService;
        private readonly ICurrentUserService _currentUser;
        private readonly CourseService _courseService;

        public SlideshowService(SimpleDbContext context,
                           ISimpleService services,
                           CacheService cacheService,
                           FileInfoService fileInfoService,
                           ICurrentUserService currentUser,
                           CourseService courseService) : base(services)
        {
            _context = context;
            _cacheService = cacheService;
            _fileInfoService = fileInfoService;
            _currentUser = currentUser;
            _courseService = courseService;
        }

        public async Task<SlideshowOutputModel> GetAsync(Guid? slideshowId)
        {
            if (!slideshowId.HasValue)
            {
                throw AppResultException.Status409Conflict("参数错误,轮播图Id参数不能为Null!");
            }

            var slideshowInfo = await _context.Set<SlideshowManage>().Include(c => c.Image).FirstOrDefaultAsync(c => c.Id == slideshowId);

            if (slideshowInfo == null)
            {
                throw AppResultException.Status409Conflict("未找轮播图相关数据!");
            }

            var outResult = MapperHelper.Map<SlideshowOutputModel>(slideshowInfo);
            return outResult;
        }

        public async Task<PageResultModel<SlideshowOutputModel>> GetPageAsync(SlideshowQueryPageInputModel input)
        {
            var result = new PageResultModel<SlideshowOutputModel>();
            var query = _context.Set<SlideshowManage>().Include(c => c.Image).AsQueryable();

            Expression<Func<SlideshowManage, bool>>? multipleSampleCodeConditions = null;
            if (!string.IsNullOrWhiteSpace(input.ShowRange))
            {
                multipleSampleCodeConditions = input.ShowRange.Select(no => (Expression<Func<SlideshowManage, bool>>)(x => EF.Functions.Like(x.ShowRange, $"%{no}%")))?.ConcatOr();
            }

            if (multipleSampleCodeConditions != null)
            {
                query = query.Where(multipleSampleCodeConditions);
            }

            // 排序
            query = query.OrderByDescending(c => c.SortValue).ThenByDescending(m => m.CreatedTime);

            // 获取总数量
            result.TotalRows = await query.CountAsync();

            // 分页查询
            query = query.Page(input.PageNo, input.PageSize);
            var slideshowOutResultList = await query.ToListAsync();
            result.Rows = MapperHelper.Map<List<SlideshowOutputModel>>(slideshowOutResultList);

            result.SetPage(input);
            result.CountTotalPage();

            return result;
        }


        public async Task<int> AddAsync(SlideshowCreateOrUpdateModel model)
        {
            if (model == null)
            {
                throw AppResultException.Status409Conflict("参数不能为Null!");
            }

            if (model.ImageFile == null)
            {
                throw AppResultException.Status409Conflict("请上传图片!");
            }

            if (model.Source == 1)
            {
                if (!model.ObjectId.HasValue)
                {
                    throw AppResultException.Status409Conflict("请选择文章或课程!");
                }
            }
            else if (model.Source == 2)
            {
                if (string.IsNullOrWhiteSpace(model.HttpURL))
                {
                    throw AppResultException.Status409Conflict("请填写外部链接地址!");
                }
            }

            var slideshowInfo = MapperHelper.Map<SlideshowManage>(model);
            if (model.ImageFile != null)
            {
                var fileId = (await _fileInfoService.BusinessUploadAsync(new List<Microsoft.AspNetCore.Http.IFormFile> { model.ImageFile }, FileSource.Carousel, string.Empty))?.FirstOrDefault();
                slideshowInfo.Image = new SlideshowManageImage { FiledId = fileId, FileName = model.ImageFile.FileName, FileSize = GetFileSize(model.ImageFile.Length) };
            }

            if (slideshowInfo.Source == 1)
            {
                if (slideshowInfo.SourceType == 1)
                {
                    // 文章
                    var article = await (await OrganizationFilter(_context.Set<ArticleManage>().Include(c => c.ArticleCategory))).FirstOrDefaultAsync(c => c.Id == model.ObjectId);
                    if (article != null)
                    {
                        slideshowInfo.ContentTitle = $"{article.ArticleCategory?.CategoryName}/{article.Title}";
                    }
                }
                else if (slideshowInfo.SourceType == 2)
                {
                    // 课程
                    var course = await (await OrganizationFilter(_context.Set<Course>().Include(c => c.CourseType))).FirstOrDefaultAsync(c => c.Id == model.ObjectId);
                    if (course != null)
                    {
                        slideshowInfo.ContentTitle = $"{course?.CourseType?.Name}/{course?.CourseName}";
                    }
                }
            }

            await _context.AddAsync(slideshowInfo);
            return await _context.SaveChangesAsync();
        }

        private string GetFileSize(long size)
        {
            var num = 1024.00;
            if (size < num)
                return size + " B";
            if (size < Math.Pow(num, 2))
                return (size / num).ToString("f2") + " KB";
            if (size < Math.Pow(num, 3))
                return (size / Math.Pow(num, 2)).ToString("f2") + " MB";
            if (size < Math.Pow(num, 4))
                return (size / Math.Pow(num, 3)).ToString("f2") + " GB";
            return (size / Math.Pow(num, 4)).ToString("f2") + " TB";
        }

        public async Task<int> UpdateAsync(SlideshowCreateOrUpdateModel model)
        {
            if (!model.Id.HasValue)
            {
                throw AppResultException.Status409Conflict("参数错误,轮播图Id参数不能为Null!");
            }

            if (model.Source == 1 && model.SourceType == 2)
            {
                throw AppResultException.Status409Conflict("课程功能正在研发中!");
            }

            if (model.Source == 1)
            {
                if (!model.ObjectId.HasValue)
                {
                    throw AppResultException.Status409Conflict("请选择文章或课程!");
                }
            }
            else if (model.Source == 2)
            {
                if (string.IsNullOrWhiteSpace(model.HttpURL))
                {
                    throw AppResultException.Status409Conflict("请填写外部链接地址!");
                }
            }

            var slideshowInfo = await _context.Set<SlideshowManage>().Include(c => c.Image)
                .Where(m => model.Id == m.Id)
                .FirstOrDefaultAsync();

            if (slideshowInfo == null)
            {
                throw AppResultException.Status404NotFound("未找到轮播图相关数据，更新失败！");
            }

            if (model.ImageFile != null)
            {
                var fileId = await _fileInfoService.UploadAsync(new FileInfo.Models.FileInfoInputModel { File = model.ImageFile, BusinessType = FileSource.Carousel });

                if (slideshowInfo.Image != null)
                {
                    slideshowInfo.Image.FiledId = fileId;
                    slideshowInfo.Image.FileName = model.ImageFile.FileName;
                    slideshowInfo.Image.FileSize = GetFileSize(model.ImageFile.Length);
                }
            }

            if (slideshowInfo.Source == 1)
            {
                if (slideshowInfo.SourceType == 1)
                {
                    // 文章
                    var article = await (await OrganizationFilter(_context.Set<ArticleManage>().Include(c => c.ArticleCategory))).FirstOrDefaultAsync(c => c.Id == model.ObjectId);
                    if (article != null)
                    {
                        slideshowInfo.ContentTitle = $"{article.ArticleCategory?.CategoryName}/{article.Title}";
                    }
                }
                else if (slideshowInfo.SourceType == 2)
                {
                    // 课程
                    var course = await (await OrganizationFilter(_context.Set<Course>().Include(c => c.CourseType))).FirstOrDefaultAsync(c => c.Id == model.ObjectId);
                    if (course != null)
                    {
                        slideshowInfo.ContentTitle = $"{course?.CourseType?.Name}/{course?.CourseName}";
                    }
                }
            }

            slideshowInfo.HttpURL = model.HttpURL;
            slideshowInfo.Source = model.Source;
            slideshowInfo.IsShow = model.IsShow.Value;
            slideshowInfo.ObjectId = model.ObjectId;
            slideshowInfo.ShowRange = model.ShowRange;
            slideshowInfo.SortValue = model.SortValue.Value;
            slideshowInfo.SourceType = model.SourceType;
            slideshowInfo.Title = model.Title;
            _context.Update(slideshowInfo);
            int ret = await _context.SaveChangesAsync();

            if (ret == 0)
            {
                throw AppResultException.Status200OK("更新记录数为0");
            }

            return ret;
        }

        public async Task<int> DeleteAsync(List<Guid?> ids)
        {
            if (ids == null || !ids.Any())
            {
                throw AppResultException.Status409Conflict("参数错误,轮播图Id参数不能为Null!");
            }

            var slideshowOutResultList = await _context.Set<SlideshowManage>().Include(c => c.Image)
                .Where(m => ids.Contains(m.Id))
                .ToListAsync();

            if (slideshowOutResultList == null || !slideshowOutResultList.Any())
            {
                throw AppResultException.Status404NotFound("未找到轮播图相关数据，删除失败！");
            }

            // 先更新数据库
            _context.RemoveRange(slideshowOutResultList);
            int ret = await _context.SaveChangesAsync();
            if (ret == 0)
            {
                throw AppResultException.Status200OK("更新记录数为0");
            }

            return ret;
        }

        public async Task<List<SlideshowOutputModel>> GetAll()
        {
            var query = await OrganizationFilter(_context.Set<SlideshowManage>().Include(c => c.Image));
            var result = await query.ToListAsync();
            if (result == null || !result.Any())
            {
                return new List<SlideshowOutputModel>();
            }

            return MapperHelper.Map<List<SlideshowOutputModel>>(result) ?? new List<SlideshowOutputModel>();
        }

        /// <summary>
        /// 获取内部资源（包含课题和文章）
        /// </summary>
        /// <returns></returns>
        public async Task<List<InternalResourcesOutputModel>> GetAllInternalResources()
        {
            var articleList = await OrganizationFilter(_context.Set<ArticleManage>().Include(c => c.ArticleCategory));
            var courseList = await OrganizationFilter(_context.Set<Course>().Include(c => c.CourseType));
            var curriculumList = new List<object>();
            return new List<InternalResourcesOutputModel>() {
               new InternalResourcesOutputModel
               {
                   Key = 1,
                   Name = "文章",
                   Values = articleList?.ToDictionary(c=>c.Id,c=>$"{c.ArticleCategory?.CategoryName}/{c.Title}")?.Select(c=>new InternalResourcesDto{ Key=c.Key,Value=c.Value})?.ToList() ?? new List<InternalResourcesDto>()
               },
               new InternalResourcesOutputModel
               {
                   Key = 2,
                   Name = "课程",
                   Values =courseList?.ToDictionary(c=>c.Id,c=>$"{c.CourseType?.Name}/{c.CourseName}")?.Select(c=>new InternalResourcesDto{ Key=c.Key,Value=c.Value})?.ToList() ?? new List<InternalResourcesDto>()
               }
            };
        }
    }
}
